package com.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import com.helpers.SystemProperties;

public class SymmetricCryptor {

	private Key secretKey = null;

	private static String ALGORITHM = "AES";
	private static int KEY_BYTES=256;

	public static void main(String[] args) {
		SymmetricCryptor ac = new SymmetricCryptor(true);
		String k=new String(Base64.encodeBase64(ac.getSecretKey().getEncoded()));
		System.out.println("SecretKey: "+k);
		System.out.println("--------------------");
		String text = "Hallo du Pfeife";
		byte[] encodedByte = ac.encrypt(text);
		//String encodedString = new String(encodedByte);
		//System.out.println(encodedString);
		System.out.println(new String(ac.decrypt(encodedByte)));
		System.out.println("--------------------");
		
		File fsec=new File("D://key.sec");
		ac.writeKey(fsec);
		SecretKey sk=ac.readKey(fsec);
		
		System.out.println("--------------------");
		
		System.out.println(new String(ac.getSecretKey().getEncoded()).equals(new String(sk.getEncoded())));
				
	}

	public SymmetricCryptor(boolean createNewKey) {
		if(createNewKey)
			generateKey();
	}

	private void generateKey() {
		try {
			KeyGenerator kg = KeyGenerator .getInstance(ALGORITHM);
			kg.init(KEY_BYTES);
			this.secretKey = kg.generateKey();
		} catch (NoSuchAlgorithmException e) {
			System.out.println("" + e.getMessage());
		}
	}

	
	/**
	 * Encrypt the plain text using public key.
	 * 
	 * @param text
	 *            : original plain text
	 * @param key
	 *            :The public key
	 * @return Encrypted text
	 * @throws java.lang.Exception
	 */
	public byte[] encrypt(String text) {
		byte[] base64text = null;
		try {
			// get an RSA cipher object and print the provider
			final Cipher cipher = Cipher.getInstance(ALGORITHM);
			// encrypt the plain text using the public key
			cipher.init(Cipher.ENCRYPT_MODE, this.secretKey);
			byte[] cipherText = cipher.doFinal(text.getBytes());
			base64text = Base64.encodeBase64(cipherText);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return base64text;
	}

	/**
	 * Decrypt text using private key.
	 * 
	 * @param text
	 *            :encrypted text
	 * @param key
	 *            :The private key
	 * @return plain text
	 * @throws java.lang.Exception
	 */
	public String decrypt(byte[] text) {
		byte[] dectyptedText = null;
		try {
			// get an RSA cipher object and print the provider
			final Cipher cipher = Cipher.getInstance(ALGORITHM);
			byte[] base64text = Base64.decodeBase64(text);
			// decrypt the text using the private key
			cipher.init(Cipher.DECRYPT_MODE, this.secretKey);
			dectyptedText = cipher.doFinal(base64text);
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return new String(dectyptedText);
	}

	public void writeKey(File f) {
		FileOutputStream out;
		try {
			out = new FileOutputStream(f);
			byte[] ky = this.secretKey.getEncoded();
			byte[] base64Key = Base64.encodeBase64(ky);
			out.write(base64Key);
			out.close();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

		
	
	public SecretKey readKey(File f){
		SecretKey secKey=null;
        try {
            FileInputStream pubKeyStream = new FileInputStream(f);  
            byte[] pubKeyBytes = new byte[KEY_BYTES]; 
			pubKeyStream.read(pubKeyBytes);
			pubKeyStream.close();  
			byte[] base64Key = Base64.decodeBase64(pubKeyBytes);
			
			secKey = new SecretKeySpec(base64Key, ALGORITHM);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}  
         
        return secKey;
	}
	
	
	public SecretKey readKey(String key64){
		SecretKey secKey=null;
        try {
            byte[] secKeyBytes = key64.getBytes();
            byte[] base64Key = Base64.decodeBase64(secKeyBytes);
			secKey = new SecretKeySpec(base64Key, ALGORITHM); 
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}  
         
        return secKey;
	}

	public Key getSecretKey() {
		return secretKey;
	}

	public void setSecretKey(Key secretKey) {
		this.secretKey = secretKey;
	}
	
	
}
